package TDAMapeo;
import TDALista.*;

public class MapeoHashAbierto<K,V> implements TDAMapeo<K,V> {

	protected TDAMapeo<K,V> [] arr;
	protected final double  factor = 0.9;
	protected int cant;
	protected int N;
	
	public MapeoHashAbierto() {
		N = 7;
		cant = 0;
		arr = (TDAMapeo<K,V>[]) new MapeoConLista[N];
		for(int i = 0; i<N;i++){
			arr[i] = new MapeoConLista<K,V>();
		}
	}
	
	public V get(K k) throws InvalidKeyException{
		if(k == null) throw new InvalidKeyException("");
		V aux = arr[h(k)].get(k);
		
		return aux;
		
	}

	public int size() {
		return cant;
	}

	public boolean isEmpty() {
		return size() == 0;
	}

	public V put(K key, V value) throws InvalidKeyException {
		if(key == null) throw new InvalidKeyException("");
		
		if(factorCarga()>factor){
			reHash();
		}
		V aux =arr[h(key)].put(key, value);
		if(aux==null)cant++;
		return aux;
		
	}

	public V remove(K key) throws InvalidKeyException {
		if(key == null) throw new InvalidKeyException("");
		
		V aux = arr[h(key)].remove(key);
		if(aux != null) cant--;
		return aux;
	}

	public Iterable<K> keys() {
		PositionList<K> claves = new DoubleLinkedList<K>();
		for(Entry<K,V> e : entries()){
			claves.addLast(e.getKey());
		}
		return claves;
	}

	public Iterable<V> values() {
		PositionList<V> claves = new DoubleLinkedList<V>();
		for(Entry<K,V> e : entries()){
			claves.addLast(e.getValue());
		}
		return claves;
	}

	public Iterable<Entry<K, V>> entries() {
		PositionList<Entry<K,V>> lista = new DoubleLinkedList<Entry<K,V>>();
		for(int i = 0; i<N; i++){
			for(Entry<K,V>e : arr[i].entries()){
				lista.addLast(e);
			}
		}
		return lista;
		
	}
	
	private int h(K k){
		//Funcion MAD
		return ((1*Math.abs(k.hashCode())+2) % 101) % N;
		
	}
	
	private double factorCarga(){
		return (double) cant/N;
	}
	
	private void reHash() throws InvalidKeyException{
		TDAMapeo<K,V> aux[] = (TDAMapeo<K,V>[])  new MapeoConLista[N*11];
		for(int i = 0;i<N*11;i++){
			aux[i] = new MapeoConLista<K,V>();
		}
		for(Entry<K,V> e : entries()){
			aux[h(e.getKey())].put(e.getKey(), e.getValue());
		}
		
		N = N*11;
		arr = aux;
	}
	
}
